﻿using System;

using System.Collections.Generic;
using System.Text;
using Silvermoon.Controls;

namespace Silvermoon.Windows
{
    public class StyleDictionary
    {
        #region fields

        private Dictionary<int, StyleBase> classStyles = new Dictionary<int, StyleBase>(4);
        private Dictionary<string, StyleBase> namedStyles;

        #endregion
        #region props

        protected Dictionary<string, StyleBase> NamedStyles
        {
            get
            {
                if (namedStyles == null) namedStyles = new Dictionary<string, StyleBase>(4);
                return namedStyles;
            }
        }

        private readonly Type baseControlType = typeof(Control);

        #endregion
        #region methods

        public StyleBase GetStyle(Control c)
        {
            StyleBase result;
            string name = c.StyleName;
            if (!string.IsNullOrEmpty(name) && namedStyles != null)
            {
                if (namedStyles.TryGetValue(name, out result)) return result;
            }


            Type type = c.GetType();

            int key = type.GetHashCode();
            if (classStyles.TryGetValue(key, out result)) return result;

            type = type.BaseType;
            while (type != baseControlType)
            {
                int subkey = type.GetHashCode();
                if (classStyles.TryGetValue(subkey, out result))
                {
                    classStyles.Add(key, result);
                    return result;
                }
                type = type.BaseType;
            }
            // classStyles.Add(key, null);
            return null;
        }

        public void SetClass(Type type, StyleBase style)
        {
            int key = type.GetHashCode();
            classStyles[key] = style;
        }

        public void SetNamed(StyleBase style)
        {
            string name = style.Name;
            if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("style", "Style must have a name.");
            NamedStyles[name] = style;
        }

        public void RemoveNamed(StyleBase style)
        {
            string name = style.Name;
            if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("style", "Style must have a name.");
            if (namedStyles != null)
            {
                namedStyles.Remove(name);
            }

        }

        public void SetClass<C>(StyleBase style) where C : Control
        {
            int key = typeof(C).GetHashCode();
            classStyles[key] = style;
        }

        public void RemoveClass(Type type)
        {
            int key = type.GetHashCode();
            classStyles.Remove(key);
        }

        public void RemoveClass<C>() where C : Control
        {
            int key = typeof(C).GetHashCode();
            classStyles.Remove(key);
        }

        public static StyleDictionary Merge(StyleDictionary source, StyleDictionary merge)
        {
            if (source == null) return merge;
            else if (merge == null) return source;

            foreach (var pair in merge.classStyles)
            {
                source.classStyles[pair.Key] = pair.Value;
            }
            if (merge.namedStyles != null)
            {
                foreach (var pair in merge.namedStyles)
                {
                    source.NamedStyles[pair.Key] = pair.Value;
                }
            }
            return source;
        }

        #endregion
    }
}
